package de.jmda.fx.node.behaviour;

import javafx.geometry.Bounds;
import javafx.scene.Node;
import javafx.scene.input.MouseEvent;

import org.apache.log4j.Logger;

import de.jmda.fx.node.EventHandler;

public class BehaviourMouseDragging
		extends AbstractNodeBehaviour<MouseEvent>
		implements Behaviour<MouseEvent>
{
	private final static Logger LOGGER =
			Logger.getLogger(BehaviourMouseDragging.class);

	private BehaviourMouseDraggingEvents behaviourMouseDraggingEvents;

	public BehaviourMouseDragging(
			Node node, BehaviourMouseDraggingEvents behaviourMouseDraggingEvents)
	{
		super(node);

		this.behaviourMouseDraggingEvents = behaviourMouseDraggingEvents;

	  javafx.event.EventHandler<? super MouseEvent> currentMouseEventHandler =
	  		node.onMouseDraggedProperty().get();
	  
	  EventHandler<MouseEvent> eventHandler;

	  if (currentMouseEventHandler == null)
	  {
//	  	EventHandler<T> eventHandler = new EventHandler<T>();
	  	eventHandler = new EventHandler<MouseEvent>();
	  	eventHandler.add(this);
	  	node.onMouseDraggedProperty().set(eventHandler);
	  }
	  else if (currentMouseEventHandler instanceof EventHandler)
		{
//	  	EventHandler<T> eventHandler = (EventHandler<T>) currentMouseEventHandler;
	  	eventHandler = (EventHandler<MouseEvent>) currentMouseEventHandler;
//	  	EventHandler<?> eventHandler = (EventHandler<?>) currentMouseEventHandler;
//	  	EventHandler<? extends MouseEvent> eventHandler =
//	  			(EventHandler<? extends MouseEvent>) currentMouseEventHandler;
//			EventHandler<? super MouseEvent> eventHandler =
//			    (EventHandler<? super MouseEvent>) currentMouseEventHandler;
			eventHandler.add(this);
	  	node.onMouseDraggedProperty().set(eventHandler);
	  }
		else
		{
			LOGGER.error(
					"failure adding behaviour " + getClass().getName() + " to " +
					currentMouseEventHandler.getClass().getName() + " event handler");
		}
	}

	@Override
  public void showBehaviour(MouseEvent mouseEventCurrent)
  {
		// store current mouse event coordinates
		double mouseEventCurrentX = mouseEventCurrent.getSceneX();
		double mouseEventCurrentY = mouseEventCurrent.getSceneY();
		
		double mouseEventMostRecentX = behaviourMouseDraggingEvents.getMouseDraggingMostRecent().getSceneX();
		double mouseEventMostRecentY = behaviourMouseDraggingEvents.getMouseDraggingMostRecent().getSceneY();
		
		double dragX = mouseEventCurrentX - mouseEventMostRecentX;
		double dragY = mouseEventCurrentY - mouseEventMostRecentY;

		double nodeLayoutX = node.getLayoutX();
		double nodeLayoutY = node.getLayoutY();

		double nodeNewX = nodeLayoutX + dragX;
		double nodeNewY = nodeLayoutY + dragY;
		
		Bounds boundsInLocal = node.getBoundsInLocal();
		
		if (nodeNewX < 0)
		{
			nodeNewX = 0;
		}
		else if ((nodeNewX + boundsInLocal.getWidth()) >
		         node.getScene().getWidth())
		{
			nodeNewX = (node.getScene().getWidth() - boundsInLocal.getWidth());
		}
		
		if (nodeNewY < 0)
		{
			nodeNewY = 0;
		}
		else if ((nodeNewY + boundsInLocal.getHeight()) >
		         node.getScene().getHeight())
		{
			nodeNewY = (node.getScene().getHeight() - boundsInLocal.getHeight());
		}

		// reposition node to new coordinates
		node.setLayoutX(nodeNewX);
		node.setLayoutY(nodeNewY);
		
		behaviourMouseDraggingEvents.setMouseDragging(mouseEventCurrent);
  }
}